package com.young.ums.web;

import com.young.common.util.Result;
import com.young.common.util.StringUtils;
import com.young.interfaces.log.annotation.Log;
import com.young.ums.model.User;
import com.young.ums.model.Dept;
import com.young.ums.model.Role;
import com.young.ums.service.*;
import com.young.ums.util.AuthHelper;
import com.young.ums.util.UmsConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 获取树控制器
 * @author imrookie
 * @date 2018/10/9
 */
@Controller
@RequestMapping(value = "/ums/tree", method = {RequestMethod.GET, RequestMethod.POST})
public class TreeController {

    private static final Logger logger = LoggerFactory.getLogger(TreeController.class);

    @Resource(name="deptService")
    IDeptService deptService;

    @Resource(name="roleService")
    IRoleService roleService;

    @Resource(name="userService")
    IUserService userService;

    @Resource
    IRoleDeptService roleDeptService;

    @Resource
    IDataAuthService dataAuthService;//数据权限

    /**
     * 获取单位角色树
     * @param dept
     * @param request
     * @return
     */
    @Log("获取单位角色树")
    @RequestMapping("/getRoleTree")
    @ResponseBody
    public Object getRoleTree(Dept dept, HttpServletRequest request) {
        AuthHelper.setAuthWhenEnableAuthIsNull(dept);//权限启用参数没有传时默认启用权限设置
        dept.setType(UmsConstants.DICTIONARY.DEPT_TYPE_COMPANY);//单位查询
        //单位列表
        List<Dept> list = deptService.getListAsTree(dept);
        if (list == null || list.size() == 0){
            return Result.buildSuccess();
        }
        /*//通过循环查询各单位下的角色
        if (list != null && list.size() > 0){
            for (Dept dept1 : list){
                List<Role> roles = roleService.getListByCompanyId(dept1.getId());
                dept1.setRoleList(roles);
            }
        }*/
        //当单位数据量较大时,循环带来的网络开销过于大,所以优化为一次性将角色都查出来
        //查询角色列表
        Role role = new Role();
        AuthHelper.setAuthWhenEnableAuthIsNull(role);//启用数据权限
        List<Role> roleList = roleService.getList(role);

        //将单位列表和角色列表关联起来
        if (roleList != null && roleList.size() > 0){
            //list转map,优化后续的查询性能
            Map<String, Dept> deptMap = new HashMap<String, Dept>(list.size());
            for (Dept dept1 : list){
                deptMap.put(dept1.getId(), dept1);
            }

            for (Role role1 : roleList){
                String companyId = role1.getCompanyId();//该角色所属的单位编号
                Dept dept1 = deptMap.get(companyId);//从map中找到对应的单位
                if (dept1 == null){
                    logger.warn("[查询单位角色树] 角色[{}]的所属单位[{}]在查询到的单位集合中匹配不到对应单位", role1.getId(), role1.getCompanyId());
                    continue;
                }
                if (dept1.getRoleList() == null){
                    dept1.setRoleList(new ArrayList<Role>());
                }
                dept1.getRoleList().add(role1);
            }
        }

        return Result.buildSuccess(list);
    }

    /**
     * 获取可以使用的单位角色树(角色用户页面)
     * @param dept
     * @param request
     * @return
     */
    @Log("获取可以使用的单位角色树(角色用户页面)")
    @RequestMapping("/getRoleTreeContainsCommonRole")
    @ResponseBody
    public Object getRoleTreeContainsCommonRole(Dept dept, HttpServletRequest request) {
        AuthHelper.setAuthWhenEnableAuthIsNull(dept);//权限启用参数没有传时默认启用权限设置
        dept.setType(UmsConstants.DICTIONARY.DEPT_TYPE_COMPANY);//单位查询
        //单位列表
        List<Dept> list = deptService.getListAsTree(dept);
        if (list == null || list.size() == 0){
            return Result.buildSuccess();
        }
        //查询角色列表
        Role role = new Role();
        AuthHelper.setAuthWhenEnableAuthIsNull(role);//启用数据权限
        List<Role> roleList = roleService.getList(role);

        //将单位列表和角色列表关联起来
        if (roleList != null && roleList.size() > 0){
            //list转map,优化后续的查询性能
            Map<String, Dept> deptMap = new HashMap<String, Dept>(list.size());
            for (Dept dept1 : list){
                deptMap.put(dept1.getId(), dept1);
            }

            for (Role role1 : roleList){
                String companyId = role1.getCompanyId();//该角色所属的单位编号
                Dept dept1 = deptMap.get(companyId);//从map中找到对应的单位
                if (dept1 == null){
                    logger.warn("[查询单位角色树(含共享角色)] 角色[{}]的所属单位[{}]在查询到的单位集合中匹配不到对应单位", role1.getId(), role1.getCompanyId());
                    continue;
                }
                if (dept1.getRoleList() == null){
                    dept1.setRoleList(new ArrayList<Role>());
                }
                dept1.getRoleList().add(role1);
            }
        }

        //查询可以使用的公共角色
        if (StringUtils.isNotBlank(dept.getLoginUserId())) {
            //查询单位管理权限
            List<Dept> companyList = dataAuthService.getManageRangeCompany(dept.getLoginUserId());
            if (companyList != null && companyList.size() > 0) {//存在管理权限
                List<String> companyIds = new ArrayList<>(companyList.size());//管理范围单位编号集合
                for (Dept company : companyList) {
                    if (company != null) {
                        companyIds.add(company.getId());
                    }
                }
                if (companyIds != null && companyIds.size() > 0) {
                    logger.info("[查询单位角色树(含共享角色)] 当前用户[{}]拥有单位管理范围为:{},查询这些单位关联的共享角色", dept.getLoginUserId(), companyIds);

                    List<Role> commonRoles2 = roleService.getParentOpenToDirectChildRoleList(companyIds);//直属单位共享给自己的角色
                    if (commonRoles2 != null && commonRoles2.size() > 0) {
                        Dept commonNode = new Dept();
                        commonNode.setName("直属上级的公开角色");
                        commonNode.setRoleList(commonRoles2);
                        list.add(commonNode);
                    }

                    List<Role> commonRoles3 = roleService.getAllParentOpenToAllChildRoleList(companyIds);//所有上级单位共享给自己的角色
                    if (commonRoles3 != null && commonRoles3.size() > 0) {
                        Dept commonNode = new Dept();
                        commonNode.setName("所有上级的公开角色");
                        commonNode.setRoleList(commonRoles3);
                        list.add(commonNode);
                    }

                    List<Role> commonRoles = roleDeptService.getRoleListByCompanyIds(companyIds);
                    if (commonRoles != null && commonRoles.size() > 0) {
                        Dept commonNode = new Dept();
                        commonNode.setName("其他可用角色");
                        commonNode.setRoleList(commonRoles);
                        list.add(commonNode);
                    }
                }

            }
        }

        return Result.buildSuccess(list);
    }

    /**
     * 获取单位用户树
     * @param dept
     * @param request
     * @return
     */
    @Log("获取单位用户树")
    @RequestMapping("/getCompanyUserTree")
    @ResponseBody
    public Object getCompanyUserTree(Dept dept, HttpServletRequest request) {
        AuthHelper.setAuthWhenEnableAuthIsNull(dept);//权限启用参数没有传时默认启用权限设置
        dept.setType(UmsConstants.DICTIONARY.DEPT_TYPE_COMPANY);//单位查询
        //查询单位列表
        List<Dept> list = deptService.getListAsTree(dept);
        if (list == null || list.size() == 0){
            return Result.buildSuccess();
        }
        //通过循环查询各单位下的用户
        /*if (list != null && list.size() > 0){
            for (Dept dept1 : list){
                List<User> users = userService.getListByCompanyId(dept1.getId());
                dept1.setUserList(users);
            }
        }*/
        //当单位数据量较大时,循环带来的网络开销过于大,所以优化为一次性将用户都查出来
        //查询用户列表
        User user = new User();
        AuthHelper.setAuthWhenEnableAuthIsNull(user);//启用数据权限
        List<User> userList = userService.getListAsTree(user);

        //将单位列表和用户列表关联起来
        if (userList != null && userList.size() > 0){
            //list转map,优化后续的查询性能
            Map<String, Dept> deptMap = new HashMap<String, Dept>(list.size());
            for (Dept dept1 : list){
                deptMap.put(dept1.getId(), dept1);
            }

            for (User user1 : userList){
                String companyId = user1.getCompanyId();//该用户所属的单位编号
                Dept dept1 = deptMap.get(companyId);//从map中找到对应的单位
                if (dept1 == null){
                    logger.warn("[查询单位用户树] 用户[{}]的所属单位[{}]在查询到的单位集合中匹配不到对应单位", user1.getId(), user1.getCompanyId());
                    continue;
                }
                if (dept1.getUserList() == null){
                    dept1.setUserList(new ArrayList<User>());
                }
                dept1.getUserList().add(user1);
            }
        }
        return Result.buildSuccess(list);
    }

    /**
     * 获取单位树
     * @param dept
     * @param rootId 树的根节点
     * @param request
     * @return
     */
    @Log("获取单位树")
    @RequestMapping("/getCompanyTree")
    @ResponseBody
    public Object getCompanyTree(Dept dept, String rootId, HttpServletRequest request) {
        if (StringUtils.isNotBlank(rootId)) {
            dept.setEnableAuth(false);//关闭数据权限
            Dept root = deptService.get(rootId);
            if (root == null) {
                logger.info("[查询单位树] 不存在根节点={},直接返回", rootId);
                //若跟节点不存在,则直接返回
                return Result.buildSuccess();
            }
            List<Dept> list = new ArrayList<Dept>();
            list.add(root);
            dept.setManageRangeList(list);//设置管理范围为指定根节点
            logger.info("[查询单位树] 根节点={}", rootId);
        } else {
            AuthHelper.setAuthWhenEnableAuthIsNull(dept);//权限启用参数没有传时默认启用权限设置
        }
        dept.setType(UmsConstants.DICTIONARY.DEPT_TYPE_COMPANY);//单位查询
        List<Dept> list = deptService.getListAsTree(dept);
        return Result.buildSuccess(list);
    }

    /**
     * 获取部门树
     * @param dept
     * @param request
     * @return
     */
    @Log("获取部门树")
    @RequestMapping("/getDeptTree")
    @ResponseBody
    public Object getDeptTree(Dept dept, HttpServletRequest request) {
        AuthHelper.setAuthWhenEnableAuthIsNull(dept);//权限启用参数没有传时默认启用权限设置
        dept.setType(UmsConstants.DICTIONARY.DEPT_TYPE_DEPT);//单位查询
        List<Dept> list = deptService.getListAsTree(dept);
        return Result.buildSuccess(list);
    }

    /**
     * 获取组织机构树
     * @param dept
     * @param request
     * @return
     */
    @Log("获取组织机构树")
    @RequestMapping("/getOrgTree")
    @ResponseBody
    public Object getOrgTree(Dept dept, HttpServletRequest request) {
        AuthHelper.setAuthWhenEnableAuthIsNull(dept);//权限启用参数没有传时默认启用权限设置
        List<Dept> list = deptService.getListAsTree(dept);
        return Result.buildSuccess(list);
    }
}
